/**
 * @Auther: zhatiai
 * @Date:2024/2/22 11:20
 */

package server

import (
	"context"
	"fmt"
	"github.com/cihub/seelog"
	"kyland.com/eagle/lib/cache"
	"kyland.com/eagle/lib/config"
	"kyland.com/eagle/lib/log"
	"kyland.com/eagle/lib/node"
	"kyland.com/eagle/manager"
	"os"
	"time"
)

func Init() func() {
	ctx, cancel := context.WithCancel(context.Background())

	// 初始化系统配置
	if err := initConfig(); err != nil {
		fmt.Println(fmt.Errorf("init config error: %v", err))
		os.Exit(1)
	}

	initNodeMinBandwidth()
	detectNodesStatus(ctx)
	//testNodeBandwidth(ctx)
	cache.NewCache()
	return func() {
		seelog.Flush()
		cancel()
	}
}

func initNodeMinBandwidth() {
	eagleConfig, err := config.Config.Get("bandwidth")
	if err != nil {
		seelog.Errorf("get ipfs config failed: %v", err)
	}

	node.MinBandwidth = float64(eagleConfig.UInt("minvalue", 10))
}

func initConfig() error {
	if err := config.LoadConfig(); err != nil {
		return fmt.Errorf("load config failed: %v", err)
	}
	if err := log.InitLogWithConfig(); err != nil {
		return fmt.Errorf("init log failed: %v", err)
	}

	return nil
}

func detectNodesStatus(ctx context.Context) {
	node.NodesMap = make(map[string]int)
	nodes := manager.GetNodes()
	for _, mem := range nodes {
		if mem.Status == node.NODE_ALIVE {
			node.NodesMap[mem.Addr] = node.NodeAlive
		}
	}

	ticker := time.NewTicker(30 * time.Second)
	go func() {
		for {
			select {
			case <-ctx.Done():
				ticker.Stop()
				return
			case <-ticker.C:
				//seelog.Infof("DetectNodesStatus Tick at: %d", t.Second())
				nodes = manager.GetNodes()
				tmp := make(map[string]int)
				for _, mem := range nodes {
					if mem.Status == node.NODE_ALIVE {
						tmp[mem.Addr] = node.NodeAlive
					}

				}
				manager.Mutex.Lock()
				for _, mem := range nodes {
					_, ok := node.NodesMap[mem.Addr]
					if ok {
						if mem.Status != node.NODE_ALIVE {
							delete(node.NodesMap, mem.Addr)
						}
					}

					if mem.Status == node.NODE_ALIVE {
						node.NodesMap[mem.Addr] = node.NodeAlive
					}
				}

				for each, _ := range node.NodesMap {
					_, ok := tmp[each]
					if !ok {
						delete(node.NodesMap, each)
					}
				}
				manager.Mutex.Unlock()
			}
		}
	}()
}
